import 'package:flutter/material.dart';

class SpinnerText extends StatefulWidget {
    
    final String text;
    
    const SpinnerText({Key key, this.text = ''}) : super(key: key);
    
    @override
    _SpinnerTextState createState() => _SpinnerTextState();
}

class _SpinnerTextState extends State<SpinnerText> with SingleTickerProviderStateMixin {
    
    String topText = '';
    String bottomText = '';
    
    Animation spinAnimation;
    
    AnimationController spinTextAnimationController;
    
    @override
    void initState() {
        super.initState();
        bottomText = widget.text;
        spinTextAnimationController = AnimationController(vsync: this, duration: Duration(seconds: 1))
            ..addListener(() {
                setState(() {
                
                });
            })
            ..addStatusListener((AnimationStatus status) {
                if (status == AnimationStatus.completed) {
                    bottomText = topText;
                    topText = '';
                    spinTextAnimationController.value = 0.0;
                }
            });
        spinAnimation = CurvedAnimation(
            parent: spinTextAnimationController,
            curve: Curves.easeIn
        );
    }
    
    @override
    void dispose() {
        spinTextAnimationController.dispose();
        super.dispose();
    }
    
    @override
    Widget build(BuildContext context) {
        return ClipRect(
            clipper: RectClip(), //平移动画超出了Stack的边界，此处需要裁剪
            child: Stack(
                children: <Widget>[
                    
                    FractionalTranslation(
                        translation: Offset(0, spinAnimation.value - 1.0),
                        child: Text(
                            topText,
                            style: TextStyle(
                                color: Colors.white,
                                fontSize: 16.0,
                            ),
                        ),
                    ),
                    FractionalTranslation(
                        translation: Offset(0.0, spinAnimation.value),
                        child: Text(
                            bottomText,
                            style: TextStyle(
                                color: Colors.white,
                                fontSize: 16.0,
                            ),
                        ),
                    ),
                
                ],
            
            ),
        );
    }
    
    @override
    void didUpdateWidget(SpinnerText oldWidget) {
        super.didUpdateWidget(oldWidget);
        
        if (oldWidget.text != widget.text) {
            topText = widget.text;
            
            spinTextAnimationController.forward();
        }
    }
    
}

class RectClip extends CustomClipper<Rect> {
    @override
    getClip(Size size) {
        return Rect.fromLTWH(0, 0, size.width, size.height);
    }
    
    @override
    bool shouldReclip(CustomClipper oldClipper) {
        return true;
    }
    
}